// System Unit
// Resource Loading Support

(*************)
(* Interface *)
(*************)
{$IFDEF Include_Modules_Header}

 Type RTLProc_GetModuleResource = Function(Instance: NativeUInt): NativeUInt;
 Var GetModuleResource: RTLProc_GetModuleResource = NIL;

 { ResString support }

 Type
  PResStringRec = ^TResStringRec;
  TResStringRec = Packed Record
   ModulePtr: Pointer; {Pointer to an address inside the module}
   Identifier: Cardinal;
  END;
  // Note: ModulePtr was actually a pointer to HModule, which is linked to the HInstance variable of the SysInit unit
  // However, we now have made it a function entry to prevent HInstance from mutation, so the linking is actually wrong.
  // (linked to a random address? unresolved import?)
  // But, the pointer does actually point to somewhere inside the module, so we can still get HModule by GetModuleHandleEx

 Type RTLProc_LoadResStringFx = Function(Const ResStringRec: PResStringRec; Buffer: PWideChar; Size: Cardinal): Cardinal;
 Var LoadResStringFx: RTLProc_LoadResStringFx = NIL;

 // Compiler Magic Function
 Function LoadResString(Const ResStringRec: PResStringRec): String;
 Type RTLProc_LoadResString = Function(Const ResStringRec: PResStringRec): String;

 Const
  // Defines 'static string' length used by system unit functions,
  //  so that memory manager is not required
  RTL_ResStr_MsgLen = 127;
  RTL_ResStr_CapLen = 63;

 //==================
 // RTL Extensions
 //==================
 Type
  TRTLEx_Resource = Record
   GetModuleResource: RTLProc_GetModuleResource;
   LoadResStringFx: RTLProc_LoadResStringFx;
   LoadResString: RTLProc_LoadResString;
  END;

 Procedure RTLExtend_Resource(Var Ex: TRTLEx_Resource);

{$ENDIF Include_Modules_Header}
(******************)
(* Implementation *)
(******************)
{$IFDEF Include_Modules_Implement}

 Function _RTL_GetModuleResource(Instance: NativeUInt): NativeUInt;
  BEGIN
   // Just return the current module resource
   Result:= Instance;
  END;

 Function _RTL_LoadResStringFx(Const ResStringRec: PResStringRec; Buffer: PWideChar; Size: Cardinal): Cardinal;
  Function _LOC_GetModuleHandle(Const ModulePtr: Pointer): NativeUInt;
   Const
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = $00000004;
    GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = $00000002;
    QueryFlag = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS OR GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
   BEGIN
    _WIN_GetModuleHandleEx(QueryFlag, PChar(ModulePtr), Result);
   END;
  Const ResStr_RevMask = $FFFF0000;
  BEGIN
   Result:= 0;
   With ResStringRec^ do
    IF (Identifier AND ResStr_RevMask) = 0
     then Result:= _WIN_LoadString(GetModuleResource(_LOC_GetModuleHandle(ModulePtr)), Identifier, Buffer, Size)
     else Buffer[Result]:= #0; { Hmm... What could this be? }
  END;

 Function _RTL_LoadResString(Const ResStringRec: PResStringRec): String;
  ASM
   JMP _INT_NotImplemented
  END;

 Var RTL_LoadResString: RTLProc_LoadResString = _RTL_LoadResString;

 Function LoadResString(Const ResStringRec: PResStringRec): String;
  ASM
   JMP RTL_LoadResString
  END;

 //==================
 // RTL Extensions
 //==================

 Procedure RTLExtend_Resource(Var Ex: TRTLEx_Resource);
  BEGIN
   _INT_RTL_DoEx(@GetModuleResource, @Ex.GetModuleResource);
   _INT_RTL_DoEx(@LoadResStringFx, @Ex.LoadResStringFx);
   _INT_RTL_DoEx(@RTL_LoadResString, @Ex.LoadResString);
  END;

 Procedure _INT_Resource_Init;
  BEGIN
   GetModuleResource:= _RTL_GetModuleResource;
   LoadResStringFx:= _RTL_LoadResStringFx;
   // RTL_LoadResString : Already initialized
  END;

{$ENDIF Include_Modules_Implement}
(******************)
(* Initialization *)
(******************)
{$IFDEF Include_Modules_Initialize}
{$ENDIF Include_Modules_Initialize}
(****************)
(* Finalization *)
(****************)
{$IFDEF Include_Modules_Finalize}
{$ENDIF Include_Modules_Finalize}
